libtiff RGB image to greyscale + loading and saving
This example shows you how to load a RGB tiff image, convert it to greyscale and save it as 32 and 8bit greyscale images. It will also write the same RGB image to another file.
#include "tiffio.h"
#include <iostream>
#include <math.h>
#include <vector>
using namespace std;
class Image {
public:
Image() {
}
void load_tiff(string input_filename) {
m_image_data.clear();
TIFF* tif = TIFFOpen(input_filename.c_str(), "r");
if (tif) {
uint32 w, h;
size_t npixels;
uint32* raster;
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
npixels = w * h;
m_width = w;
m_height = h;
raster = (uint32*) _TIFFmalloc(npixels * sizeof (uint32));
if (raster != NULL) {
if (TIFFReadRGBAImageOriented(tif, w, h, raster,ORIENTATION_TOPLEFT, 0)) {
for(size_t n=0;n<npixels;n++) m_image_data.push_back(raster[n]);
}
_TIFFfree(raster);
}
TIFFClose(tif);
}
}
void save_tiff_rgb(string output_filename) {
TIFF *output_image;
// Open the TIFF file
if((output_image = TIFFOpen(output_filename.c_str(), "w")) == NULL){
cerr << "Unable to write tif file: " << output_filename << endl;
}
// We need to set some values for basic tags before we can add any data
TIFFSetField(output_image, TIFFTAG_IMAGEWIDTH, m_width);
TIFFSetField(output_image, TIFFTAG_IMAGELENGTH, m_height);
TIFFSetField(output_image, TIFFTAG_BITSPERSAMPLE, 8);
TIFFSetField(output_image, TIFFTAG_SAMPLESPERPIXEL, 4);
TIFFSetField(output_image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
TIFFSetField(output_image, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE);
TIFFSetField(output_image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
// Write the information to the file
TIFFWriteEncodedStrip(output_image, 0, &m_image_data[0], m_width*m_height * 4);
// Close the file
TIFFClose(output_image);
}
void save_tiff_grey_32bit(string output_filename) {
TIFF *output_image;
// Open the TIFF file
if((output_image = TIFFOpen(output_filename.c_str(), "w")) == NULL){
cerr << "Unable to write tif file: " << output_filename << endl;
}
// We need to set some values for basic tags before we can add any data
TIFFSetField(output_image, TIFFTAG_IMAGEWIDTH, m_width);
TIFFSetField(output_image, TIFFTAG_IMAGELENGTH, m_height);
TIFFSetField(output_image, TIFFTAG_BITSPERSAMPLE, 32);
TIFFSetField(output_image, TIFFTAG_SAMPLESPERPIXEL, 1);
TIFFSetField(output_image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
TIFFSetField(output_image, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE);
TIFFSetField(output_image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
// Write the information to the file
TIFFWriteEncodedStrip(output_image, 0, &m_image_data[0], m_width*m_height * 4);
// Close the file
TIFFClose(output_image);
}
void save_tiff_grey_8bit(string output_filename) {
TIFF *output_image;
// Open the TIFF file
if((output_image = TIFFOpen(output_filename.c_str(), "w")) == NULL){
cerr << "Unable to write tif file: " << output_filename << endl;
}
// We need to set some values for basic tags before we can add any data
TIFFSetField(output_image, TIFFTAG_IMAGEWIDTH, m_width);
TIFFSetField(output_image, TIFFTAG_IMAGELENGTH, m_height);
TIFFSetField(output_image, TIFFTAG_BITSPERSAMPLE, 8);
TIFFSetField(output_image, TIFFTAG_SAMPLESPERPIXEL, 1);
TIFFSetField(output_image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
TIFFSetField(output_image, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE);
TIFFSetField(output_image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE);
// convert data to 8bit
vector<uint8_t> data;
for(size_t n=0;n<m_image_data.size();n++) {
data.push_back(255-(m_image_data[n]/(256*256*256)));
}
// Write the information to the file
TIFFWriteEncodedStrip(output_image, 0, &data[0], m_width*m_height);
// Close the file
TIFFClose(output_image);
}
void make_greyscale() {
for(size_t n=0;n<m_image_data.size();n++) {
double r = TIFFGetR(m_image_data[n]);
double g = TIFFGetG(m_image_data[n]);
double b = TIFFGetB(m_image_data[n]);
double grey = (0.3*r) + (0.59*g) + (0.11*b); // See http://en.wikipedia.org/wiki/Grayscale
m_image_data[n] = grey * 256 * 256 * 256;
}
}
vector<uint32_t> m_image_data;
size_t m_width;
size_t m_height;
};
int main(int argc, char* argv[])
{
Image input;
input.load_tiff(string(argv[1]));
input.save_tiff_rgb(string(argv[2]));
input.make_greyscale();
input.save_tiff_grey_32bit(string(argv[3]));
input.save_tiff_grey_8bit(string(argv[4]));
}
Compile as:
g++ makegrey.cpp -ltiff
And run as:
./a.out inputfilename.tif rgb.tif 8bitgrey.tif 32bitgrey.tif
Note: The 8bit version is slightly different than the 32bit version. It converts the data such that 0 represents white. This is because Preview.app, at least in MacOS X Lion, does not seem to be able to cope with 0 being black.
This has not been applied to the 32bit output, so this will display incorrectly in Preview. However it will display correctly in Imagemagick.